From 6ae724388531135f6c405d21543abdde972f255f Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Sat, 14 Nov 2009 10:32:59 +0000 Subject: [PATCH] tmem: fix domain shutdown problem/race Tmem fails to put_domain so a dying domain never gets properly shut down. Also, fix race condition when domain is dying by not allowing any new ops to succeed. Signed-off-by: Dan Magenheimer --- xen/common/tmem.c | 12 ++++++++++++ xen/common/tmem_xen.c | 1 + xen/include/xen/tmem_xen.h | 4 +++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/xen/common/tmem.c b/xen/common/tmem.c index 55c2aabdad..806f543962 100644 --- a/xen/common/tmem.c +++ b/xen/common/tmem.c @@ -2229,6 +2229,12 @@ EXPORT long do_tmem_op(tmem_cli_op_t uops) DUP_START_CYC_COUNTER(flush,succ_get); DUP_START_CYC_COUNTER(flush_obj,succ_get); + if ( client != NULL && tmh_client_is_dying(client) ) + { + rc = -ENODEV; + goto out; + } + if ( unlikely(tmh_get_tmemop_from_client(&op, uops) != 0) ) { printk("tmem: can't get tmem struct from %s\n",client_str); @@ -2392,6 +2398,12 @@ EXPORT void tmem_destroy(void *v) if ( client == NULL ) return; + if ( !tmh_client_is_dying(client) ) + { + printk("tmem: tmem_destroy can only destroy dying client\n"); + return; + } + if ( tmh_lock_all ) spin_lock(&tmem_spinlock); else diff --git a/xen/common/tmem_xen.c b/xen/common/tmem_xen.c index b7a308b019..12f249149b 100644 --- a/xen/common/tmem_xen.c +++ b/xen/common/tmem_xen.c @@ -314,6 +314,7 @@ EXPORT void tmh_client_destroy(tmh_client_t *tmh) #ifndef __i386__ xmem_pool_destroy(tmh->persistent_pool); #endif + put_domain(tmh->domain); xfree(tmh); } diff --git a/xen/include/xen/tmem_xen.h b/xen/include/xen/tmem_xen.h index 787e1467ff..0e19c90680 100644 --- a/xen/include/xen/tmem_xen.h +++ b/xen/include/xen/tmem_xen.h @@ -280,7 +280,7 @@ typedef struct page_info pfp_t; /* this appears to be unreliable when a domain is being shut down */ static inline struct client *tmh_client_from_cli_id(cli_id_t cli_id) { - struct domain *d = get_domain_by_id(cli_id); + struct domain *d = get_domain_by_id(cli_id); /* incs d->refcnt! */ if (d == NULL) return NULL; return (struct client *)(d->tmem); @@ -291,6 +291,8 @@ static inline struct client *tmh_client_from_current(void) return (struct client *)(current->domain->tmem); } +#define tmh_client_is_dying(_client) (!!_client->tmh->domain->is_dying) + static inline cli_id_t tmh_get_cli_id_from_current(void) { return current->domain->domain_id; -- 2.30.2